﻿// CLRLoader.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "CLRLoader.h"
#include "..\\nproxy\\nproxy.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name

// Forward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
void DrawAlphaBlend (HWND hWnd, HDC hdcwnd);
void LoadCLR(HWND hWnd);

int APIENTRY _tWinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPTSTR    lpCmdLine,
	int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	// TODO: Place code here.
	InitializeCLR();

	MSG msg;
	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_CLRLOADER, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CLRLOADER));

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CLRLOADER));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_CLRLOADER);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;

	hInst = hInstance; // Store instance handle in our global variable

	hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

	if (!hWnd)
	{
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Parse the menu selections:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		case ID_FILE_LOADCLR:
			LoadCLR(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: Add any drawing code here...
		DrawAlphaBlend(hWnd, hdc);

		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

void DrawAlphaBlend (HWND hWnd, HDC hdcwnd)
{
	HDC hdc;               // handle of the DC we will create  
	BLENDFUNCTION bf;      // structure for alpha blending 
	HBITMAP hbitmap;       // bitmap handle 
	BITMAPINFO bmi;        // bitmap header 
	VOID *pvBits;          // pointer to DIB section 
	ULONG   ulWindowWidth, ulWindowHeight;      // window width/height 
	ULONG   ulBitmapWidth, ulBitmapHeight;      // bitmap width/height 
	RECT    rt;            // used for getting window dimensions 
	UINT32   x,y;          // stepping variables 
	UCHAR ubAlpha;         // used for doing transparent gradient 
	UCHAR ubRed;        
	UCHAR ubGreen;
	UCHAR ubBlue;
	float fAlphaFactor;    // used to do premultiply 

	// get window dimensions 
	GetClientRect(hWnd, &rt);

	// calculate window width/height 
	ulWindowWidth = rt.right - rt.left;  
	ulWindowHeight = rt.bottom - rt.top;  

	// make sure we have at least some window size 
	if ((!ulWindowWidth) || (!ulWindowHeight))
		return;

	// divide the window into 3 horizontal areas 
	ulWindowHeight = ulWindowHeight / 3;

	// create a DC for our bitmap -- the source DC for AlphaBlend  
	hdc = CreateCompatibleDC(hdcwnd);

	// zero the memory for the bitmap info 
	ZeroMemory(&bmi, sizeof(BITMAPINFO));

	// setup bitmap info  
	// set the bitmap width and height to 60% of the width and height of each of the three horizontal areas. Later on, the blending will occur in the center of each of the three areas. 
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth = ulBitmapWidth = ulWindowWidth - (ulWindowWidth/5)*2;
	bmi.bmiHeader.biHeight = ulBitmapHeight = ulWindowHeight - (ulWindowHeight/5)*2;
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;         // four 8-bit components 
	bmi.bmiHeader.biCompression = BI_RGB;
	bmi.bmiHeader.biSizeImage = ulBitmapWidth * ulBitmapHeight * 4;

	// create our DIB section and select the bitmap into the dc 
	hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0);
	SelectObject(hdc, hbitmap);

	// in top window area, constant alpha = 50%, but no source alpha 
	// the color format for each pixel is 0xaarrggbb  
	// set all pixels to blue and set source alpha to zero 
	for (y = 0; y < ulBitmapHeight; y++)
		for (x = 0; x < ulBitmapWidth; x++)
			((UINT32 *)pvBits)[x + y * ulBitmapWidth] = 0x000000ff; 

	bf.BlendOp = AC_SRC_OVER;
	bf.BlendFlags = 0;
	bf.SourceConstantAlpha = 0x7f;  // half of 0xff = 50% transparency 
	bf.AlphaFormat = 0;             // ignore source alpha channel 

	if (!AlphaBlend(hdcwnd, ulWindowWidth/5, ulWindowHeight/5, 
		ulBitmapWidth, ulBitmapHeight, 
		hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, bf))
		return;                     // alpha blend failed 

	// in middle window area, constant alpha = 100% (disabled), source  
	// alpha is 0 in middle of bitmap and opaque in rest of bitmap  
	for (y = 0; y < ulBitmapHeight; y++)
		for (x = 0; x < ulBitmapWidth; x++)
			if ((x > (int)(ulBitmapWidth/5)) && (x < (ulBitmapWidth-ulBitmapWidth/5)) &&
				(y > (int)(ulBitmapHeight/5)) && (y < (ulBitmapHeight-ulBitmapHeight/5)))
				//in middle of bitmap: source alpha = 0 (transparent). 
				// This means multiply each color component by 0x00. 
				// Thus, after AlphaBlend, we have a, 0x00 * r,  
				// 0x00 * g,and 0x00 * b (which is 0x00000000) 
				// for now, set all pixels to red 
				((UINT32 *)pvBits)[x + y * ulBitmapWidth] = 0x00ff0000; 
			else
				// in the rest of bitmap, source alpha = 0xff (opaque)  
				// and set all pixels to blue  
				((UINT32 *)pvBits)[x + y * ulBitmapWidth] = 0xff0000ff; 
	//endif;

	bf.BlendOp = AC_SRC_OVER;
	bf.BlendFlags = 0;
	bf.AlphaFormat = AC_SRC_ALPHA;  // use source alpha  
	bf.SourceConstantAlpha = 0xff;  // opaque (disable constant alpha) 

	if (!AlphaBlend(hdcwnd, ulWindowWidth/5, ulWindowHeight/5+ulWindowHeight, ulBitmapWidth, ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, bf))
		return;

	// bottom window area, use constant alpha = 75% and a changing 
	// source alpha. Create a gradient effect using source alpha, and  
	// then fade it even more with constant alpha 
	ubRed = 0x00;
	ubGreen = 0x00;
	ubBlue = 0xff;

	for (y = 0; y < ulBitmapHeight; y++)
		for (x = 0; x < ulBitmapWidth; x++)
		{
			// for a simple gradient, base the alpha value on the x  
			// value of the pixel  
			ubAlpha = (UCHAR)((float)x / (float)ulBitmapWidth * 255);
			//calculate the factor by which we multiply each component 
			fAlphaFactor = (float)ubAlpha / (float)0xff; 
			// multiply each pixel by fAlphaFactor, so each component  
			// is less than or equal to the alpha value. 
			((UINT32 *)pvBits)[x + y * ulBitmapWidth] 
			= (ubAlpha << 24) |                       //0xaa000000 
				((UCHAR)(ubRed * fAlphaFactor) << 16) |  //0x00rr0000 
				((UCHAR)(ubGreen * fAlphaFactor) << 8) | //0x0000gg00 
				((UCHAR)(ubBlue   * fAlphaFactor));      //0x000000bb 
		}

		bf.BlendOp = AC_SRC_OVER;
		bf.BlendFlags = 0;
		bf.AlphaFormat = AC_SRC_ALPHA;   // use source alpha  
		bf.SourceConstantAlpha = 0xbf;   // use constant alpha, with  
		// 75% opaqueness 

		AlphaBlend(hdcwnd, ulWindowWidth/5, 
			ulWindowHeight/5+2*ulWindowHeight, ulBitmapWidth, 
			ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, 
			ulBitmapHeight, bf);

		// do cleanup 
		DeleteObject(hbitmap);
		DeleteDC(hdc);

}

void LoadCLR(HWND hWnd)
{

	WCHAR pszBuffer[32];

	wsprintfW(pszBuffer, L"Fibonacci(8)=%d", Fibonacci(8));
	MessageBoxW(hWnd, pszBuffer, L"Prompt", MB_OK | MB_ICONINFORMATION);

	wsprintfW(pszBuffer, L"Fibonacci(61)=%d", Fibonacci(61));
	MessageBoxW(hWnd, pszBuffer, L"Prompt", MB_OK | MB_ICONINFORMATION);

	wsprintfW(pszBuffer, L"Fibonacci(-5)=%d", Fibonacci(-5));
	MessageBoxW(hWnd, pszBuffer, L"Prompt", MB_OK | MB_ICONINFORMATION);

	wsprintfW(pszBuffer, L"Fibonacci(150)=%d", Fibonacci(150));
	MessageBoxW(hWnd, pszBuffer, L"Prompt", MB_OK | MB_ICONINFORMATION);
}

